using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Toenda.Foundation.IO {
	/// <summary>
	/// DirectoryCopy
	/// </summary>
	public class DirectoryCopy {
		/// <summary>
		/// Initializes a new instance of the FileCopyEventHandler class.
		/// </summary>
		public delegate void FileCopyEventHandler(int amount, int index, string text);
		/// <summary>
		/// Occurs when [file copy response].
		/// </summary>
		public event FileCopyEventHandler FileCopyResponse;

		/// <summary>
		/// Initializes a new instance of the FileCopyFinishEventhandler class.
		/// </summary>
		public delegate void FileCopyFinishEventhandler(bool successfull, string text);
		/// <summary>
		/// Occurs when [file copy finish].
		/// </summary>
		public event FileCopyFinishEventhandler FileCopyFinish;

		/// <summary>
		/// Default constructor
		/// </summary>
		public DirectoryCopy() {
		}

		/// <summary>
		/// Get the amount of all files from a directory (not recursivly)
		/// </summary>
		/// <param name="sourceDir">The source dir.</param>
		/// <returns></returns>
		public int GetAmountOfFiles(string sourceDir) {
			return this.GetAmountOfFiles(sourceDir, false);
		}

		/// <summary>
		/// Get the amount of all files recursivly from a directory
		/// </summary>
		/// <param name="sourceDir">The source dir.</param>
		/// <param name="recursive">if set to <c>true</c> [recursive].</param>
		/// <returns></returns>
		public int GetAmountOfFiles(string sourceDir, bool recursive) {
			int amount = 2;

			if(!sourceDir.EndsWith(Path.DirectorySeparatorChar.ToString())) {
				sourceDir += Path.DirectorySeparatorChar;
			}

			DirectoryInfo di = new DirectoryInfo(sourceDir);
			amount += di.GetDirectories("*", SearchOption.AllDirectories).GetUpperBound(0);
			amount += di.GetFiles("*", SearchOption.AllDirectories).GetUpperBound(0);

			return amount;
		}

		/// <summary>
		/// Copy a complete folder with contents to another destionation
		/// </summary>
		/// <param name="sourceDir">The source path.</param>
		/// <param name="destDir">The new destination path.</param>
		/// <param name="fRecursive">A value that indicates if the directory should be copied recursively.</param>
		/// <param name="overWrite">A value that indicates if the directory should overwrite existend files and directories.</param>
		/// <param name="amount">The amount of all files (needed for the event).</param>
		/// <param name="index">The index.</param>
		/// <param name="isRootQuery">if set to <c>true</c> [is root query].</param>
		public void RecursiveCopyFiles(
			string sourceDir,
			string destDir,
			bool fRecursive,
			bool overWrite,
			int amount,
			ref int index,
			bool isRootQuery) {
			int i = 0;
			int posSep = 0;
			string sDir = null;
			string[] aDirs = null;
			string sFile = null;
			string[] aFiles = null;

			if(!sourceDir.EndsWith(Path.DirectorySeparatorChar.ToString())) {
				sourceDir += Path.DirectorySeparatorChar;
			}

			if(!destDir.EndsWith(Path.DirectorySeparatorChar.ToString())) {
				destDir += Path.DirectorySeparatorChar;
			}

			if(fRecursive) {
				aDirs = Directory.GetDirectories(sourceDir);

				for(i = 0; i <= aDirs.GetUpperBound(0); i++) {
					posSep = aDirs[i].LastIndexOf(@"\");

					sDir = aDirs[i].Substring((posSep + 1), aDirs[i].Length - (posSep + 1));

					Directory.CreateDirectory(destDir + sDir);

					this.FileCopyResponse(
						amount,
						index,
						"Directory: " + sDir
					);

					this.RecursiveCopyFiles(
						aDirs[i],
						(destDir + sDir),
						fRecursive,
						overWrite,
						amount,
						ref index,
						false
					);
				}
			}

			aFiles = Directory.GetFiles(sourceDir);

			for(i = 0; i <= aFiles.GetUpperBound(0); i++) {
				posSep = aFiles[i].LastIndexOf(@"\");

				sFile = aFiles[i].Substring((posSep + 1), aFiles[i].Length - (posSep + 1));

				try {
					File.Copy(aFiles[i], destDir + sFile, false);

					this.FileCopyResponse(
						amount,
						index,
						"File: " + sFile
					);
				}
				catch(Exception ex) {
					string error = ex.Message;

					if(overWrite == false) {
						//Console.WriteLine("Skipping..." + ex.Message);
					}
					else {
						File.Copy(aFiles[i], destDir + sFile, true);
						//Console.WriteLine("Overwriting old " + sFile + " in " + destDir);
					}
				}
			}

			if(isRootQuery) {
				this.FileCopyFinish(true, "");
			}
		}
	}
}
